#include <iostream>
#include <string>
#include <cstring>
#include <iterator>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <stdio.h>
#include <string.h>
using namespace std;
#define _SKIP_LINE_ do{scanf("%*[^\n]"); getc(stdin);}while(0)
const short size = 50;
char GRID[size+1][size+2];
short M, N, W;
vector<string> words;
typedef pair<short, short> Pos;

struct Compare {
  bool operator() (const Pos& lhs, const Pos& rhs) const {
	  if(lhs.first == rhs.first)
		  return lhs.second < rhs.second;
	  else return lhs.first < rhs.first;
  }
};

typedef set<Pos, Compare> Positions;

map<char, Positions> Hash;

void print() {
	for(short i = 1; i <= M; ++i) {	
		for(short j = 1; j <= N; ++j)
			cout << GRID[i][j];
		cout << endl;
	}
	copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); 
}

Pos Search(const string& word) {
	Positions::const_iterator p = Hash[word[0]].begin();
	Positions::const_iterator end = Hash[word[0]].end();
	short n = word.size();
	const char* w = word.c_str();
	bool found = true;
	while(p != end) {
		const short i = p->first;
		const short j = p->second;
		// right
		if(j+n-1 <= N && strncmp(GRID[i]+j, w, n) == 0) { 
			break;
		}
		// left
		if(j-n+1 >= 1) { 
			for(short c=j, x=0; c > 0 && x < n; --c,++x) {
				if(GRID[i][c] != w[x]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// down
		if(i+n-1 <= M) {
			for(short r=i; r < i+n; ++r) {
				if(GRID[r][j] != w[r-i]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// up
		if(i-n+1 >= 1) {
			for(short r=i, x=0; r > 0 && x < n; --r,++x) {
				if(GRID[r][j] != w[x]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// up right digonal
		if(i-n+1 >= 1 &&  j+n-1 <= N) {
			for(short r=i, c=j; r > 0 && c < j+n; --r, ++c) {
				if(GRID[r][c] != w[c-j]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// down right digonal
		if(i+n-1 <= M &&  j+n-1 <= N) {
			for(short r=i, c=j; r < i+n && c < j+n; ++r, ++c) {
				if(GRID[r][c] != w[c-j]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// up left digonal
		if(i-n+1 >= 1 &&  j-n+1 >= 1) {
			for(short r=i, c=j, x=0; r > 0 && c > 0 && x < n; --r, --c, ++x) {
				if(GRID[r][c] != w[x]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		// down left digonal
		if(i+n-1 <= M &&  j-n+1 >= 1) {
			for(short r=i, c=j; r < i+n && c > 0; ++r, --c) {
				if(GRID[r][c] != w[r-i]) {
					found = false;
					break;
				}
			}
			if(found == true) break;
			else found = true;
		}
		++p;
	}
	if(p == end) return make_pair(0, 0);
	return *p;
}

void task(string& word) {
	Pos i = Search(word);
	cout << i.first << " " << i.second << endl;
}

void HashGrid() {
	for(short i=1; i <= M; ++i)
		for(short j=1; j <= N; ++j) 
			Hash[GRID[i][j]].insert(make_pair(i, j));
}

/* main
 *  * */
int main() {
	//memset(GRID, 0, (size+1)*(size+2)*sizeof(char));
	short test_cases  = 0;
	cin >> test_cases;
	while(test_cases > 0 && cin.eof() != true) {
		cin >> M >> N;
		_SKIP_LINE_;
		// READ GRID
		for(short r=1; r <= M; ++r) {
			cin.getline(GRID[r]+1, N+1);
			transform(GRID[r]+1, GRID[r]+1+N, GRID[r]+1, ::tolower);
			_SKIP_LINE_;
			cin.clear();
		}
		HashGrid();
		// READ WORD
		cin >> W;
		_SKIP_LINE_;
		words.clear();
		words.resize(W);
		for(short c=0; c < W; ++c) {
			cin.clear();
			getline(cin, words[c]);
#ifndef DONLINE_JUDGE
			words[c] = words[c].substr(0, words[c].size()-1);
#endif
			transform(words[c].begin(), words[c].end(), words[c].begin(), ::tolower);
		}
		//print();
		for_each(words.begin(), words.end(), task);	
		if(--test_cases > 0)
			cout << endl;
	}
	return 0;
}
